{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "0",
   "metadata": {},
   "source": [
    "[![image](https://studiolab.sagemaker.aws/studiolab.svg)](https://studiolab.sagemaker.aws/import/github/opengeos/geoai/blob/main/docs/examples/dataviz/vector_viz.ipynb)\n",
    "[![image](https://img.shields.io/badge/Open-Planetary%20Computer-black?style=flat&logo=microsoft)](https://pccompute.westeurope.cloudapp.azure.com/compute/hub/user-redirect/git-pull?repo=https://github.com/opengeos/geoai&urlpath=lab/tree/geoai/docs/examples/dataviz/vector_viz.ipynb&branch=main)\n",
    "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://githubtocolab.com/opengeos/geoai/blob/main/docs/examples/dataviz/vector_viz.ipynb)\n",
    "\n",
    "# Visualizing Vector Data with Leafmap\n",
    "\n",
    "## Installation\n",
    "\n",
    "Uncomment the following line to install [leafmap](https://leafmap.org) if needed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# %pip install \"leafmap[vector]\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2",
   "metadata": {},
   "source": [
    "## Import libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import leafmap"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4",
   "metadata": {},
   "source": [
    "## Visualize vector data\n",
    "\n",
    "You can visualize vector data using the `add_vector` function. It supports common vector data formats, including GeoJSON, Shapefile, GeoPackage, and any other formats supported by [geopandas](https://geopandas.org)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = leafmap.Map(center=[0, 0], zoom=2)\n",
    "data = \"https://opengeos.org/data/vector/cables.geojson\"\n",
    "m.add_vector(data, layer_name=\"Cable lines\", info_mode=\"on_hover\")\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6",
   "metadata": {},
   "source": [
    "![](https://i.imgur.com/NIcnLWs.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7",
   "metadata": {},
   "source": [
    "You can style the vector with custom style callback functions. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = leafmap.Map(center=[20, 0], zoom=2)\n",
    "m.add_basemap(\"CartoDB.DarkMatter\")\n",
    "data = \"https://opengeos.org/data/vector/cables.geojson\"\n",
    "callback = lambda feat: {\"color\": feat[\"properties\"][\"color\"], \"weight\": 1}\n",
    "m.add_vector(data, layer_name=\"Cable lines\", style_callback=callback)\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9",
   "metadata": {},
   "source": [
    "![](https://i.imgur.com/mQnV53U.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10",
   "metadata": {},
   "source": [
    "## Choropleth map\n",
    "\n",
    "You can create a choropleth map using the `add_data` function. It supports GeoJSON, Shapefile, GeoPackage, and any other formats supported by [geopandas](https://geopandas.org). \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "11",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = leafmap.Map()\n",
    "data = \"https://raw.githubusercontent.com/opengeos/leafmap/master/docs/examples/data/countries.geojson\"\n",
    "m.add_data(\n",
    "    data, column=\"POP_EST\", scheme=\"Quantiles\", cmap=\"Blues\", legend_title=\"Population\"\n",
    ")\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12",
   "metadata": {},
   "source": [
    "![](https://i.imgur.com/4FV6f72.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = leafmap.Map()\n",
    "m.add_data(\n",
    "    data,\n",
    "    column=\"POP_EST\",\n",
    "    scheme=\"EqualInterval\",\n",
    "    cmap=\"Blues\",\n",
    "    legend_title=\"Population\",\n",
    ")\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14",
   "metadata": {},
   "source": [
    "![](https://i.imgur.com/KEY6zEj.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15",
   "metadata": {},
   "source": [
    "## GeoParquet\n",
    "\n",
    "Visualize GeoParquet data with leafmap and lonboard."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "16",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = \"https://opengeos.org/data/duckdb/cities.parquet\"\n",
    "gdf = leafmap.read_parquet(url, return_type=\"gdf\", src_crs=\"EPSG:4326\")\n",
    "gdf.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17",
   "metadata": {},
   "source": [
    "Visualize point data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18",
   "metadata": {},
   "outputs": [],
   "source": [
    "leafmap.view_vector(\n",
    "    gdf,\n",
    "    get_radius=20000,\n",
    "    get_fill_color=\"blue\",\n",
    "    zoom_to_layer=False,\n",
    "    map_args={\"center\": (40, -100), \"zoom\": 3, \"height\": 500},\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19",
   "metadata": {},
   "source": [
    "![](https://i.imgur.com/BBsLjvx.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20",
   "metadata": {},
   "source": [
    "Visualizing polygon data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = \"https://data.source.coop/giswqs/nwi/wetlands/DC_Wetlands.parquet\"\n",
    "gdf = leafmap.read_parquet(\n",
    "    url, return_type=\"gdf\", src_crs=\"EPSG:5070\", dst_crs=\"EPSG:4326\"\n",
    ")\n",
    "gdf.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "22",
   "metadata": {},
   "outputs": [],
   "source": [
    "leafmap.view_vector(gdf, get_fill_color=[0, 0, 255, 128])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23",
   "metadata": {},
   "source": [
    "![vector](https://i.imgur.com/HRtpiVd.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "24",
   "metadata": {},
   "source": [
    "Alternatively, you can specify a color map to visualize the data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "25",
   "metadata": {},
   "outputs": [],
   "source": [
    "color_map = {\n",
    "    \"Freshwater Forested/Shrub Wetland\": (0, 136, 55),\n",
    "    \"Freshwater Emergent Wetland\": (127, 195, 28),\n",
    "    \"Freshwater Pond\": (104, 140, 192),\n",
    "    \"Estuarine and Marine Wetland\": (102, 194, 165),\n",
    "    \"Riverine\": (1, 144, 191),\n",
    "    \"Lake\": (19, 0, 124),\n",
    "    \"Estuarine and Marine Deepwater\": (0, 124, 136),\n",
    "    \"Other\": (178, 134, 86),\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "26",
   "metadata": {},
   "outputs": [],
   "source": [
    "leafmap.view_vector(gdf, color_column=\"WETLAND_TYPE\", color_map=color_map, opacity=0.5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27",
   "metadata": {},
   "source": [
    "![vector-color](https://i.imgur.com/Ejh8hK6.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28",
   "metadata": {},
   "source": [
    "Display a legend for the data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "29",
   "metadata": {},
   "outputs": [],
   "source": [
    "leafmap.Legend(title=\"Wetland Type\", legend_dict=color_map)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30",
   "metadata": {},
   "source": [
    "![legend](https://i.imgur.com/fxzHHFN.png)\n",
    "\n",
    "## PMTiles\n",
    "\n",
    "[PMTiles](https://github.com/protomaps/PMTiles) is a single-file archive format for tiled data. A PMTiles archive can be hosted on a commodity storage platform such as S3, and enables low-cost, zero-maintenance map applications that are \"serverless\" - free of a custom tile backend or third party provider."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31",
   "metadata": {},
   "source": [
    "## Remote PMTiles\n",
    "\n",
    "Leafmap can visualize PMTiles hosted locally or remotely."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32",
   "metadata": {},
   "source": [
    "### Overture data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "33",
   "metadata": {},
   "outputs": [],
   "source": [
    "import leafmap.foliumap as leafmap"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34",
   "metadata": {},
   "source": [
    "Check the metadata of the PMTiles."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "35",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = \"https://storage.googleapis.com/ahp-research/overture/pmtiles/overture.pmtiles\"\n",
    "metadata = leafmap.pmtiles_metadata(url)\n",
    "print(f\"layer names: {metadata['layer_names']}\")\n",
    "print(f\"bounds: {metadata['bounds']}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36",
   "metadata": {},
   "source": [
    "Visualize the PMTiles."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "37",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = leafmap.Map()\n",
    "m.add_basemap(\"CartoDB.DarkMatter\")\n",
    "\n",
    "style = {\n",
    "    \"version\": 8,\n",
    "    \"sources\": {\n",
    "        \"example_source\": {\n",
    "            \"type\": \"vector\",\n",
    "            \"url\": \"pmtiles://\" + url,\n",
    "            \"attribution\": \"PMTiles\",\n",
    "        }\n",
    "    },\n",
    "    \"layers\": [\n",
    "        {\n",
    "            \"id\": \"admins\",\n",
    "            \"source\": \"example_source\",\n",
    "            \"source-layer\": \"admins\",\n",
    "            \"type\": \"fill\",\n",
    "            \"paint\": {\"fill-color\": \"#BDD3C7\", \"fill-opacity\": 0.1},\n",
    "        },\n",
    "        {\n",
    "            \"id\": \"buildings\",\n",
    "            \"source\": \"example_source\",\n",
    "            \"source-layer\": \"buildings\",\n",
    "            \"type\": \"fill\",\n",
    "            \"paint\": {\"fill-color\": \"#FFFFB3\", \"fill-opacity\": 0.5},\n",
    "        },\n",
    "        {\n",
    "            \"id\": \"places\",\n",
    "            \"source\": \"example_source\",\n",
    "            \"source-layer\": \"places\",\n",
    "            \"type\": \"fill\",\n",
    "            \"paint\": {\"fill-color\": \"#BEBADA\", \"fill-opacity\": 0.5},\n",
    "        },\n",
    "        {\n",
    "            \"id\": \"roads\",\n",
    "            \"source\": \"example_source\",\n",
    "            \"source-layer\": \"roads\",\n",
    "            \"type\": \"line\",\n",
    "            \"paint\": {\"line-color\": \"#FB8072\"},\n",
    "        },\n",
    "    ],\n",
    "}\n",
    "\n",
    "m.add_pmtiles(\n",
    "    url, name=\"PMTiles\", style=style, overlay=True, show=True, zoom_to_layer=True\n",
    ")\n",
    "\n",
    "legend_dict = {\n",
    "    \"admins\": \"BDD3C7\",\n",
    "    \"buildings\": \"FFFFB3\",\n",
    "    \"places\": \"BEBADA\",\n",
    "    \"roads\": \"FB8072\",\n",
    "}\n",
    "\n",
    "m.add_legend(legend_dict=legend_dict)\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38",
   "metadata": {},
   "source": [
    "![](https://i.imgur.com/fjWMOu3.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39",
   "metadata": {},
   "source": [
    "### Source Cooperative\n",
    "\n",
    "Visualize the [Google-Microsoft Open Buildings data](https://beta.source.coop/repositories/vida/google-microsoft-open-buildings/description) hosted on Source Cooperative.\n",
    "\n",
    "Check the metadata of the PMTiles."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = \"https://data.source.coop/vida/google-microsoft-open-buildings/pmtiles/go_ms_building_footprints.pmtiles\"\n",
    "metadata = leafmap.pmtiles_metadata(url)\n",
    "print(f\"layer names: {metadata['layer_names']}\")\n",
    "print(f\"bounds: {metadata['bounds']}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41",
   "metadata": {},
   "source": [
    "Visualize the PMTiles."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "42",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = leafmap.Map(center=[20, 0], zoom=2)\n",
    "m.add_basemap(\"CartoDB.DarkMatter\")\n",
    "m.add_basemap(\"Esri.WorldImagery\", show=False)\n",
    "\n",
    "style = {\n",
    "    \"version\": 8,\n",
    "    \"sources\": {\n",
    "        \"example_source\": {\n",
    "            \"type\": \"vector\",\n",
    "            \"url\": \"pmtiles://\" + url,\n",
    "            \"attribution\": \"PMTiles\",\n",
    "        }\n",
    "    },\n",
    "    \"layers\": [\n",
    "        {\n",
    "            \"id\": \"buildings\",\n",
    "            \"source\": \"example_source\",\n",
    "            \"source-layer\": \"building_footprints\",\n",
    "            \"type\": \"fill\",\n",
    "            \"paint\": {\"fill-color\": \"#3388ff\", \"fill-opacity\": 0.5},\n",
    "        },\n",
    "    ],\n",
    "}\n",
    "\n",
    "m.add_pmtiles(\n",
    "    url, name=\"Buildings\", style=style, overlay=True, show=True, zoom_to_layer=False\n",
    ")\n",
    "\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "43",
   "metadata": {},
   "source": [
    "![](https://i.imgur.com/kT6ng6k.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44",
   "metadata": {},
   "source": [
    "## Local PMTiles\n",
    "\n",
    "tippecanoe is required to convert vector data to pmtiles. Install it with `conda install -c conda-forge tippecanoe`.\n",
    "\n",
    "Download [building footprints](https://github.com/opengeos/open-data/blob/main/datasets/libya/Derna_buildings.geojson) of Derna, Libya."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "45",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = \"https://raw.githubusercontent.com/opengeos/open-data/main/datasets/libya/Derna_buildings.geojson\"\n",
    "leafmap.download_file(url, \"buildings.geojson\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46",
   "metadata": {},
   "source": [
    "Convert vector to PMTiles."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "47",
   "metadata": {},
   "outputs": [],
   "source": [
    "pmtiles = \"buildings.pmtiles\"\n",
    "leafmap.geojson_to_pmtiles(\n",
    "    \"buildings.geojson\", pmtiles, layer_name=\"buildings\", overwrite=True, quiet=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48",
   "metadata": {},
   "source": [
    "Start a HTTP Sever"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "49",
   "metadata": {},
   "outputs": [],
   "source": [
    "leafmap.start_server(port=8000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = f\"http://127.0.0.1:8000/{pmtiles}\"\n",
    "leafmap.pmtiles_metadata(url)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51",
   "metadata": {},
   "source": [
    "Display the PMTiles on the map."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = leafmap.Map()\n",
    "\n",
    "style = {\n",
    "    \"version\": 8,\n",
    "    \"sources\": {\n",
    "        \"example_source\": {\n",
    "            \"type\": \"vector\",\n",
    "            \"url\": \"pmtiles://\" + url,\n",
    "            \"attribution\": \"PMTiles\",\n",
    "        }\n",
    "    },\n",
    "    \"layers\": [\n",
    "        {\n",
    "            \"id\": \"buildings\",\n",
    "            \"source\": \"example_source\",\n",
    "            \"source-layer\": \"buildings\",\n",
    "            \"type\": \"fill\",\n",
    "            \"paint\": {\"fill-color\": \"#3388ff\", \"fill-opacity\": 0.5},\n",
    "        },\n",
    "    ],\n",
    "}\n",
    "\n",
    "m.add_pmtiles(url, name=\"Buildings\", show=True, zoom_to_layer=True, style=style)\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53",
   "metadata": {},
   "source": [
    "![](https://i.imgur.com/lhGri31.png)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "geo",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
